package edu.gatech.cc.hwa.server.features;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class IpChecker {

	private static String ANY_ONE_BYTES = "[0-9]{0,3}";
	private static String ANY_TWO_BYTES = ANY_ONE_BYTES+"."+ANY_ONE_BYTES;
	private static String ANY_THREE_BYTES = ANY_TWO_BYTES+"."+ANY_ONE_BYTES;
	
	static String ANY_IPv4 = ANY_THREE_BYTES+"."+ANY_ONE_BYTES;
	
	static boolean checkIp(String incomingIp, String ipRegex) {
		Pattern ipPattern = Pattern.compile(ipRegex);
		Matcher matcher = ipPattern.matcher(incomingIp);
		return matcher.matches();
	}
	
	public static String aggregateIps(List<String> ips, int minNumberToMatch) {
		if (minNumberToMatch > ips.size()) {
			return ANY_IPv4;
		}
		int maxPatternsToCheck = ips.size()-minNumberToMatch;
		
		for (int i=0;i<=maxPatternsToCheck;i++) {
			Pattern pattern = createRegexFor32Bits(ips.get(i));
			if (checkIpsForPattern(ips, pattern, minNumberToMatch)) {
				return pattern.pattern();
			}
		}
		for (int i=0;i<=maxPatternsToCheck;i++) {
			Pattern pattern = createRegexFor24Bits(ips.get(i));
			if (checkIpsForPattern(ips, pattern, minNumberToMatch)) {
				return pattern.pattern();
			}
		}
		for (int i=0;i<=maxPatternsToCheck;i++) {
			Pattern pattern = createRegexFor16Bits(ips.get(i));
			if (checkIpsForPattern(ips, pattern, minNumberToMatch)) {
				return pattern.pattern();
			}
		}
		for (int i=0;i<=maxPatternsToCheck;i++) {
			Pattern pattern = createRegexFor8Bits(ips.get(i));
			if (checkIpsForPattern(ips, pattern, minNumberToMatch)) {
				return pattern.pattern();
			}
		}
		return ANY_IPv4;
	}
	
	private static boolean checkIpsForPattern(List<String> ips, Pattern pattern, int minToMatch) {
		int patternsMatched = 0;
		for (String ip : ips) {
			Matcher m = pattern.matcher(ip);
			if (m.matches()) {
				patternsMatched++;
			}
		}
		return patternsMatched >= minToMatch;
	}

	private static Pattern createRegexFor32Bits(String ip) {
		return Pattern.compile(ip);
	}
	
	private static Pattern createRegexFor24Bits(String ip) {
		ip = ip.substring(0, ip.lastIndexOf("."));
		ip += ANY_ONE_BYTES;
		return Pattern.compile(ip);
	}
	
	private static Pattern createRegexFor16Bits(String ip) {
		int indexOfSecondDot = ip.indexOf('.');
		indexOfSecondDot = ip.indexOf('.', indexOfSecondDot+1);
		
		ip = ip.substring(0, indexOfSecondDot);
		ip += ANY_TWO_BYTES;
		return Pattern.compile(ip);
	}
	
	private static Pattern createRegexFor8Bits(String ip) {
		ip = ip.substring(0, ip.indexOf("."));
		ip += ANY_THREE_BYTES;
		return Pattern.compile(ip);
	}
}
